home *** CD-ROM | disk | FTP | other *** search
- TITLE WC - WORD COUNT UTILITY
- PAGE 55,132
- ;***********************************************************************
- ; THIS PROGRAM COUNTS BYTES, WORDS AND LINES IN A TEXT FILE.
- ;
- ; USAGE: WC filename
- ; defaults to standard input if no file name given.
- ;
- ; REQUIRES MSDOS 2 OR HIGHER
- ;
- ; BY: JON DART
- ; DEPARTMENT OF ANTHROPOLOGY
- ; UCSD C-001
- ; LA JOLLA, CA 92093
- ;
- ; VERSION 1.2, 06-JUL-86
- ; VERSION 1.1, 16-JAN-86
- ; VERSION 1.0, 08-NOV-85
- ;
- ;****** TO BUILD WC.EXE, ASSEMBLE THIS FILE AND LINK WITH ASM.LIB ******
-
- BUFSIZE EQU 8192 ;SIZE OF FILE BUFFER
- M EQU BYTE PTR 0[BX]
-
- .XLIST
- INCLUDE ASCII.DEF
- INCLUDE MSDOS2.DEF
- INCLUDE MACROS.DEF
- .LIST
-
- EXTRN COUT:NEAR,ERRORMSG:NEAR
- EXTRN TYPTX:NEAR,SKIPSP:NEAR,CPYCNT:NEAR
- EXTRN PRINTDD:NEAR
-
- STACK SEGMENT PARA STACK
- DB 512 DUP (?)
- STACK ENDS
- ASSUME SS:STACK
-
- ; MEMORY DEFINITIONS:
- ;
- DATA SEGMENT BYTE PUBLIC
- NUMEND DB 2 DUP (?) ;END OF NUMBER
- INHANDLE DW 0 ;INPUT FILE HANDLE
- ;(DEFAULTS TO STD. INPUT)
- NUMLINE DQ 0 ;NUMBER OF LINES
- NUMWORD DQ 0 ;NUMBER OF WORDS
- NUMBYTE DQ 0 ;NUMBER OF BYTES
- PREV DB 0 ;PREVIOUS CHAR., USED IN WORD COUNT
- MSG1 DB CR,LF,"Can't open: "
- FILNAM DB 80 DUP (0) ;STORAGE FOR FILE NAME
- MSG1E DB CR,LF,0
- MSG2 DB CR,LF,"Read error.",CR,LF,0
- MSG3 DB CR,LF,"Not enough memory for buffer.",CR,LF,0
- DATA ENDS
- ASSUME DS:DATA,ES:DATA
-
- BUFFER EQU 0 ;OFFSET TO BUFFER (FROM ES)
-
- CODE SEGMENT BYTE PUBLIC
- ASSUME CS:CODE
- ENTRY:
- TEST_DOS2 ;TEST FOR DOS 2.0, EXIT IF DOS 1
- MOV BX,(BUFSIZE+800H) SHR 4
- MOV AH,SET_BLOCK
- INT DOS ;SET PROGRAM+BUFFER SIZE
- JNB MEMOK ;IF OK
- MOV AX,DATA
- MOV DS,AX
- MOV DX,OFFSET MSG3
- CALL ERRORMSG ;NOT ENOUGH MEMORY
- JMP EXIT2
- MEMOK: MOV AX,DS ;GET DATA SEG
- ADD AX,800H ;ADD OFFSET TO BUFFER
- MOV ES,AX ;SET EXTRA SEG TO POINT TO BUFFER
- MOV BX,OFFSET (80H) ;GET BYTE COUNT FOR COMMAND LINE
- CMP BYTE PTR [BX],0
- JNE L_1 ;IF NOT 0
- MOV AX,DATA
- MOV DS,AX
- JMP FILLBUF ;NO COMMAND LINE INPUT, USE STD. INPUT
- L_1:
- PUSH BX
- MOV DL,M
- MOV DH,0
- ADD BX,DX
- INC BX
- MOV M,0 ;PUT 0 BYTE AT END OF COMMAND LINE
- POP BX
- INC BX
- CALL SKIPSP ;SKIP LEADING SPACES
- JNC L_2 ;IF SOMETHING ON LINE
- JMP FILLBUF
- L_2:
- PUSH ES
- MOV AX,DATA
- MOV ES,AX ;MAKE ES POINT TO DATA SEG
- MOV SI,BX
- MOV DI,OFFSET FILNAM
- MOV CX,80
- CALL CPYCNT ;SAVE FILE NAME
- POP ES
- MOV AX,DATA
- MOV DS,AX ;DONE W. LO MEMORY, SO
- ; POINT TO DATA SEG NOW
- MOV DX,OFFSET FILNAM ;DX POINTS TO FILE NAME
- MOV AL,READ_ACCESS
- MOV AH,DOS2_OPEN
- INT DOS ;TRY TO OPEN FILE
- JNC NAMEOK ;IF OK
- JMP SHORT BADOPN
- NAMEOK:
- MOV WORD PTR INHANDLE,AX ;SAVE FILE HANDLE
- JMP SHORT FILLBUF
- BADOPN:
- MOV DX,OFFSET MSG1
- CALL ERRORMSG ;BAD OPEN, SHOW MSG.
- MOV DX,OFFSET MSG1E
- CALL ERRORMSG ;ADD CR + LF
- JMP CLOSEFILE ;EXIT
-
- FILLBUF:
- MOV CX,BUFSIZE ;CX = # BYTES TO READ
- MOV BX,WORD PTR INHANDLE ;BX = FILE HANDLE
- PUSH DS
- MOV AX,ES
- MOV DS,AX ;SET DATA SEG TO WHERE BUFFER IS
- MOV DX,OFFSET BUFFER
- MOV AH,READ
- INT DOS ;FILL BUFFER FROM FILE
- POP DS ;RESTORE DATA SEG
- JC BADREAD ;IF ERROR
- MOV BX,OFFSET BUFFER
- CMP AX,0
- JNE GOTTEXT ;IF SOMETHING READ
- JMP DONE
-
- BADREAD:
- MOV DX,OFFSET MSG2
- CALL ERRORMSG
- JMP CLOSEFILE
-
- GOTTEXT:
- ADD AX,BX ;COMPUTE ADDRESS OF END OF BUFFER
- MOV DX,AX ;SAVE IN DX
- MOV DI,OFFSET NUMLINE ;NUMBER OF LINES
- MOV SI,OFFSET NUMBYTE
- BEGIN:
- COUNT: CMP DX,BX ;COUNT BYTES AND LINES
- JNE L_12 ;UNTIL END OF BUFFER
- JMP FILLBUF ;GO FILL BUFFER AGAIN
- L_12:
- MOV AL,BYTE PTR ES:[BX] ;GET BYTE FROM BUFFER
- AND AL,7FH ;STRIP HI BIT
- INC BX
- INC WORD PTR [SI] ;COUNT A BYTE
- JNC NOCARRY
- INC WORD PTR [SI+2] ;IF CARRY
- NOCARRY:
- CMP AL,SPACE ;IS SPACE?
- JE WCOUNT ;YES, POSSIBLE END OF WORD
- CMP AL,CR ;IS CR?
- JNE COUNT2 ;NO, IGNORE CHAR.
- COUNTLINE:
- INC WORD PTR DS:[DI] ;COUNT A LINE
- JNC WCOUNT
- INC WORD PTR DS:[DI+2]
- WCOUNT: CMP BYTE PTR PREV,0 ;SAW A SPACE OR CR, WAS PREV. CHAR. NULL?
- JE COUNT2
- CMP BYTE PTR PREV,CR ;OR CR?
- JE COUNT2
- CMP BYTE PTR PREV,LF ;OR LF?
- JE COUNT2
- CMP BYTE PTR PREV,SPACE ;OR SPACE?
- JE COUNT2
- CMP BYTE PTR PREV,TAB ;OR TAB?
- JE COUNT2
- INC WORD PTR NUMWORD ;NO, ASSUME END OF WORD
- JNC COUNT2
- INC WORD PTR NUMWORD+2
- COUNT2:
- MOV BYTE PTR PREV,AL
- JMP COUNT
- DONE:
- MOV AX,WORD PTR NUMBYTE
- MOV SI,AX
- MOV AX,WORD PTR NUMBYTE+2
- MOV DI,AX
- MOV AL,0
- CALL PRINTDD
- CALL TYPTX
- DB ' bytes,',SPACE+200Q
- MOV AX,WORD PTR NUMWORD
- MOV SI,AX
- MOV AX,WORD PTR NUMWORD+2
- MOV DI,AX
- MOV AL,0
- CALL PRINTDD
- CALL TYPTX
- DB ' words,',SPACE+200Q
- MOV AX,WORD PTR NUMLINE
- MOV SI,AX
- MOV AX,WORD PTR NUMLINE+2
- MOV DI,AX
- MOV AL,0
- CALL PRINTDD
- CALL TYPTX
- DB ' lines.',CR,LF+200Q
- JMP SHORT CLOSEFILE
-
- CLOSEFILE:
- MOV BX,WORD PTR INHANDLE
- CMP BX,0 ;WERE WE READING STD. INPUT?
- JE EXIT2 ;YES, NO NEED TO CLOSE
- MOV AH,DOS2_CLOSE
- INT DOS ;CLOSE FILE
- EXIT2:
- MOV AH,EXIT
- INT DOS ;EXIT TO DOS
-
- CODE ENDS
- END ENTRY